home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume8 / ease / part04 < prev    next >
Encoding:
Internet Message Format  |  1987-02-10  |  54.9 KB

  1. Subject:  v08i056:  Ease, a language for writing sendmail.cf files, Part04/04
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: ksb@j.cc.purdue.edu
  6. Mod.sources: Volume 8, Issue 56
  7. Archive-name: ease/Part04
  8.  
  9. [  A couple of things to note, here.  First, watch out for the horribly
  10.    long "usage" string -- I bet some compilers can't handle it (it should
  11.    probably be an array of text lines, anyhow).  Second, it would be
  12.    great if someone converted this program to use getopt(3), and sent the
  13.    changes on to the maintainers...  --r$  ]
  14.  
  15. #    This is a shell archive.
  16. #    Remove everything above and including the cut line.
  17. #    Then run the rest of the file through sh.
  18. #----cut here-----cut here-----cut here-----cut here----#
  19. #!/bin/sh
  20. # shar:    Shell Archiver
  21. #    Run the following text with /bin/sh to create:
  22. #    maketd
  23. mkdir maketd
  24. chdir maketd
  25. cat << \SHAR_EOF > Makefile
  26. # For a VAX
  27. DEFS=    -DBSD4_2
  28. LDFLAGS=
  29.  
  30. # For a PDP 11/70
  31. # DEFS= -DBSD2_9
  32. # LDFLAGS= -i
  33.  
  34. INCLUDE=    
  35. CFLAGS=    -O ${DEFS} ${INCLUDE}
  36. DEST=    /usr/new/bin
  37.  
  38. SRC=    abrv.c maketd.c misc.c nshpopen.c breakargs.c srtunq.c
  39. HDR=    maketd.h abrv.h nshpopen.h srtunq.h
  40. OBJ=    maketd.o abrv.o misc.o nshpopen.o breakargs.o srtunq.o
  41.  
  42. all: maketd
  43.  
  44. maketd:    ${OBJ}
  45.     ${CC} ${LDFLAGS} ${OBJ} -o maketd
  46.  
  47. clean: FRC
  48.     rm -f ${OBJ} maketd \#* *.bak core a.out
  49.  
  50. depend:    source
  51.     maketd -a ${DEFS} ${INCLUDE} ${SRC}
  52.  
  53. install: maketd
  54.     install -s -m 0751 -o binary -g system maketd ${DEST}
  55.  
  56. lint: source
  57.     lint -hpx ${SRC}
  58.  
  59. print: source
  60.     lpr -p Makefile ${HDR} ${SRC}
  61.  
  62. shar: source
  63.     shar Makefile ${SRC} ${HDR} Manual
  64.  
  65. source: Makefile ${SRC} ${HDR}
  66.  
  67. spotless: clean
  68.     rcsclean ${SRC} ${HDR} Makefile
  69.  
  70. ${SRC} ${HDR}:
  71.     co $@
  72.  
  73. FRC:
  74.  
  75. # a clever way to save a few more characters
  76. I=/usr/include/
  77. S=/usr/include/sys/
  78.  
  79. # DO NOT DELETE THIS LINE - make depend DEPENDS ON IT
  80.  
  81. abrv.o: $Ictype.h $Istdio.h abrv.c abrv.h maketd.h srtunq.h
  82.  
  83. maketd.o: $Ictype.h $Imachine/machparam.h $Isignal.h $Istdio.h $Sdir.h \
  84.     $Sfile.h $Sparam.h $Stypes.h abrv.h maketd.c maketd.h nshpopen.h \
  85.     srtunq.h
  86.  
  87. misc.o: $Istdio.h $Ssignal.h maketd.h misc.c
  88.  
  89. nshpopen.o: $Isignal.h $Istdio.h nshpopen.c
  90.  
  91. breakargs.o: $Istdio.h breakargs.c
  92.  
  93. srtunq.o: $Istdio.h $Stypes.h srtunq.c srtunq.h
  94.  
  95. # *** Do not add anything here - It will go away. ***
  96. SHAR_EOF
  97. if test 1371 -ne "`wc -c Makefile`"
  98. then
  99. echo shar: error transmitting Makefile '(should have been 1371 characters)'
  100. fi
  101. mkdir Manual
  102. chdir Manual
  103. cat << \SHAR_EOF > maketd.1l
  104. .TH MAKETD 1L "11 November 1985"
  105. .if n \{.de Q
  106. "\\$1"\\$2
  107. .\}
  108. .if t \{.de Q
  109. ``\\$1''\\$2
  110. .\}
  111. ..
  112. .SH NAME
  113. maketd \- make transitive dependencies
  114. .SH SYNOPSIS
  115. .B maketd
  116. [
  117. .I option(s)
  118. .I file(s)
  119. .SH DESCRIPTION
  120. .I Maketd
  121. computes dependencies for makefiles from sources introduced through
  122. include files.
  123. It generates lines like
  124. .Q "xx.o: e.h struct.h ../h/const.h ..." .
  125. It makes xx.o not only dependent on all files it includes,
  126. but also recursively on all files other files include.
  127. This is achieved by passing the source through the C preprocessor.
  128. .PP
  129. The directories used in the search for include files
  130. are identical to the ones used by the C compiler, because the
  131. C preprocessor is used.
  132. This also means that `#define's, `#ifdef's, etc. are evaluated.
  133. It may therefore be necessary to recompute the dependencies if
  134. any source has been changed, including the associated Makefile.
  135. .PP
  136. A typical application in a Makefile goes as follows:
  137. .nf
  138.  
  139.     INCL= \-I../include  \-I../h
  140.     CFLAGS= \-DPUCC \-DBSD4_2 ${INCL}
  141.     SRC= a.c b.c c.c
  142.  
  143.     maketd: ${SRC}
  144.         maketd \-a ${CFLAGS} ${SRC}
  145.  
  146.     # DO NOT DELETE THIS LINE \- make depend DEPENDS ON IT
  147.  
  148. .fi
  149. The generated dependencies will be inserted after the `# DO NOT DELETE...'
  150. line.
  151. Everything after this line will go away through the editing
  152. process of the Makefile.
  153. If no such line exists, a line of the expected form will be emitted,
  154. followed by the dependencies.
  155. The default filename for the Makefile is `makefile'.
  156. If `makefile' does not exist, `Makefile' is used.
  157. The \-m and \-d options override this default action.
  158. Before it is edited, the Makefile will be saved in `Makefile.bak',
  159. overwritting any existing `Makefile.bak'.
  160. .PP
  161. Several options apply.
  162. If an option takes any arguments, all arguments follow the option
  163. directly, with no spaces.
  164. If spaces are required inside an argument to an option, then
  165. quotes must be used to prevent the shell from breaking up the
  166. argument.
  167. .TP
  168. .BI \-a
  169. Normally, dependencies on files in `/usr/include' are
  170. not included \- this option also includes dependencies on those files.
  171. .TP
  172. .BI \-b
  173. Generate dependencies for binaries rather than object files.
  174. This is equivelent to specifying a null suffix.
  175. The `.o' is stripped from the filename.
  176. .TP
  177. .BI \-d
  178. Instead of editing the Makefile, dependencies are written to standard
  179. output.
  180. The standard header and trailer, `# DO NOT...' are not emitted.
  181. .TP
  182. .BI \-f
  183. Force printing of header and trailer.
  184. Normally, these are suppresed when the output file is the standard
  185. output.
  186. .TP
  187. .BI \-h
  188. Print a set of oneline descriptions to the terminal and exit.
  189. .TP
  190. .BI \-m file
  191. Instead of editing `makefile' or `Makefile', the file named
  192. .I file
  193. is edited.
  194. .TP
  195. .BI \-nonlocalo
  196. Generate dependency paths that match the source paths given.
  197. .TP
  198. .BI \-o directory
  199. Normally dependencies are of the form
  200. .Q "a.o: ....." .
  201. This option generates dependencies of the form
  202. .Q "\fIdirectory\fP/a.o:...." ,
  203. which is useful for Makefiles which store the objects in
  204. a separate subdirectory.
  205. The name of the directory must not be empty.
  206. .TP
  207. .BI \-r
  208. Causes the dependencies for a single source file to be generated and
  209. replaced in the edited Makefile.
  210. .TP
  211. .BI \-s suffix
  212. Supply a suffix for the target.
  213. The suffix should start with a `.'.
  214. The target file name should have a suffix of some sort that
  215. is delimited by a `.' that is replaced by this suffix.
  216. .TP
  217. .BI \-t target
  218. Supply a new basename for the target.
  219. .TP
  220. .BI \-x
  221. Don't shorten include files.
  222. The default action is to replace various strings with abbreviations.
  223. The Makefile is scanned to see which single letter uppercase
  224. variables are set.
  225. These definitions are remembered.
  226. The pathnames `/usr/include' and `/usr/include/sys', along with any
  227. pathnames specified with \-I options are also used in abbreviations.
  228. Unused uppercase single letters are defined, printed to the Makefile,
  229. and used.
  230. .TP
  231. .BI \-v
  232. Be verbose.
  233. Extra output is directed to
  234. .I stderr.
  235. .TP
  236. .BI \-I...
  237. Specify a directory to search for include files.
  238. This option is passed to /lib/cpp, and thus behaves identically to
  239. the same option to `cc'.
  240. .TP
  241. .BI \-D...
  242. Specify a definition.
  243. This option is passed to /lib/cpp, and thus behaves identically to
  244. the same option to `cc'.
  245. .TP
  246. .BI \-U....
  247. Specify that a variable that should not be defined.
  248. This option is passed to /lib/cpp, and thus behaves identically to
  249. the same option to `cc'.
  250. .IR cc (1).
  251. .SH "AUTHOR"
  252. Stephan v. Bechtolsheim (the shell script) (Purdue CS)
  253. .br
  254. Stephen Uitti (the C version) (PUCC)
  255. .SH "SEE ALSO"
  256. make(1), cc(1)
  257. SHAR_EOF
  258. if test 4509 -ne "`wc -c maketd.1l`"
  259. then
  260. echo shar: error transmitting maketd.1l '(should have been 4509 characters)'
  261. fi
  262. cat << \SHAR_EOF > nshpopen.3l
  263. .TH NSHPOPEN 3 "local"
  264. .SH NAME
  265. nshpopen, nshpclose \- initiate I/O to/from a process
  266. .SH SYNOPSIS
  267. .B #include <stdio.h>
  268. .PP
  269. .SM
  270. .B FILE
  271. .B *nshpopen(command, type)
  272. .br
  273. .B char *command, *type;
  274. .PP
  275. .B nshpclose(stream)
  276. .br
  277. .SM
  278. .B FILE
  279. .B *stream;
  280. .SH DESCRIPTION
  281. The arguments to 
  282. .I nshpopen
  283. are pointers to null-terminated strings containing respectively
  284. a shell command line and an I/O mode, either "r" for reading or
  285. "w" for writing.
  286. It creates a pipe between the calling process and the command
  287. to be executed.
  288. The value returned is a stream pointer that can be used (as
  289. appropriate) to write to the standard input of the command or
  290. read from its standard output.
  291. .PP
  292. A stream opened by
  293. .I nshpopen
  294. should be closed by
  295. .IR nshpclose ,
  296. which waits for the associated process to terminate
  297. and returns the exit status of the command.
  298. .PP
  299. Because open files are shared, a type "r" command may be used
  300. as an input filter, and a type "w" as an output filter.
  301. .PP
  302. .I Nshpopen
  303. breaks up the
  304. .I command
  305. argument string at spaces and tabs for the child process.
  306. However, it does not invoke a shell, and does not
  307. attempt any shell shell meta character parsing.
  308. In particular, quoted white space will still cause argument seperation.
  309. By avoiding calling a shell, pipe creation is a great deal quicker.
  310. Also, by avoiding the (rather complicated) shell meta character
  311. parsing, some types of bugs may be avoided.
  312. This is important where the security of setuid programs is involved.
  313. .SH "SEE ALSO"
  314. pipe(2),
  315. popen(3),
  316. fopen(3S),
  317. fclose(3S),
  318. system(3),
  319. wait(2),
  320. sh(1)
  321. .SH DIAGNOSTICS
  322. .I Nshpopen
  323. returns a null pointer if files or processes cannot be created,
  324. or the shell cannot be accessed.
  325. .PP
  326. .I Nshpclose
  327. returns \-1 if
  328. .I stream
  329. is not associated with an `nshpopened' command.
  330. .SH BUGS
  331. Buffered reading before opening an input filter
  332. may leave the standard input of that filter mispositioned.
  333. Similar problems with an output filter may be
  334. forestalled by careful buffer flushing, for instance, with
  335. .I fflush,
  336. see
  337. .IR fclose (3).
  338. .LP
  339. .I Nshpopen
  340. does not call a shell to do it's work.
  341. It does not attempt to process shell meta characters.
  342. Thus, it does not treat quotes, I/O redirects, or file
  343. name wildcard characters specially.
  344. This is it's incompatibility with
  345. .I popen(3).
  346. .LP
  347. This type of function should have been included with
  348. .I popen(3)
  349. in the standard I/O library.
  350. SHAR_EOF
  351. if test 2367 -ne "`wc -c nshpopen.3l`"
  352. then
  353. echo shar: error transmitting nshpopen.3l '(should have been 2367 characters)'
  354. fi
  355. cat << \SHAR_EOF > srtunq.3l
  356. .TH SRTUNQ 1L PUCC
  357. .SH NAME
  358. srtinit, srtin, srtgti, srtgets, srtfree, srtdtree
  359. .SH SYNOPSIS
  360. .B #include <stdio.h>
  361. .br
  362. .B #include <local/srtunq.h>
  363. .sp
  364. cc file.c
  365. .B \-lsrtunq
  366. .SH DESCRIPTION
  367. .I Libsrtunq.a
  368. is a set of sorting routines for a particular purpose.
  369. It's use is extracting unique items from a possibly long list,
  370. where items are likely to be replicated numerously.
  371. The list of unique items will be small enough to
  372. fit in main memory.
  373. High speed is desired.
  374. .PP
  375. The caller has control over the database through the use of a
  376. .I struct srtent
  377. variable.
  378. The subroutines provide for data entry and retrieval,
  379. memory allocation and deallocation.
  380. .SH ROUTINES
  381. .TP
  382. .ft B
  383. void srtinit(ent) struct srtent *ent;
  384. .ft
  385. This subroutine must be called before the first time
  386. any data is entered or retrieved
  387. from a database tree whose tag is pointed to by
  388. .B ent.
  389. It assumes that the database tag has not been used
  390. to store a tree, and therefore does not attempt to free
  391. any such data.
  392. .TP
  393. .ft B
  394. char *srtin(ent, string, compar) struct srtent *ent; char *string; int (*compar)();
  395. .ft
  396. The existing data tree is searched.
  397. If the string is found in the tree then nothing is done.
  398. Otherwise, space is allocated for the string and pointer structure via
  399. .I malloc(3).
  400. The string is copied to this new space.
  401. The structure is linked into the tree.
  402. If space cannot be obtained, the operation is aborted, and
  403. a pointer to an error string is returned.
  404. The data structure remains consistent, but the string is not placed in it.
  405. If the operation is successful, NULL is returned.
  406. The strings are compared and sorted with the subroutine pointed to by
  407. .I compar.
  408. This subroutine takes two string pointers as arguments.
  409. It returns zero if the strings are the same,
  410. less than zero if the first string should precede the second, and
  411. greater than zero if the second string should precede the first.
  412. If the subroutine pointer is NULL, then a simple string compare is used, which
  413. sorts in ascending ASCII order, and strings of different length comparing
  414. as unequal.
  415. .TP
  416. .ft B
  417. void srtgti(ent); struct srtent *ent;
  418. .ft
  419. This subroutine initializes the database tag pointed to by
  420. .B ent
  421. so that a tree transversal can be made via
  422. .I srtgets.
  423. .TP
  424. .ft B
  425. char *srtgets(ent); struct srtent *ent;
  426. .ft
  427. This routine extracts the next string from the data structure.
  428. The strings are returned in increasing order.
  429. When the list is exhausted, NULL is returned.
  430. .TP
  431. .ft B
  432. void srtfree(ent) struct srtent *ent;
  433. .ft
  434. This subroutine deletes a database, and re-initializes the
  435. database tag.
  436. It assumes that the database tag was initialized at one time via
  437. .I srtinit
  438. (other routines will probably also have been called).
  439. The space formally occupied by string data and pointer structures is
  440. deallocated via
  441. .I free(3).
  442. .TP
  443. .ft B
  444. void srtdtree(ent, tbl) struct srtent *ent; struct srtbl *tbl;
  445. .ft
  446. This subroutine recursively deletes a database subtree.
  447. The space formally occupied by the string data and pointer structures is
  448. deallocated via
  449. .I free(3).
  450. This routine is most likely only of use internally.
  451. .SH EXAMPLE
  452. .nf
  453. main()
  454. {
  455.     char buf[80], *p;
  456.     struct srtent d;
  457.     srtinit(&d);
  458.     while (fgets(buf, stdin, 79) != NULL)
  459.         if ((p = srtin(&d, "foo")) != NULL)
  460.             printf("test: %s\n", p);  /* warning message */
  461.     srtgti(&d);
  462.     while ((p = srtgets(&d)) != NULL)
  463.         puts(p);
  464.     srtfree(&d);
  465. }
  466. .fi
  467. .SH DIAGNOSTICS
  468. There are no messages printed by these routines.
  469. Catchable errors are returned as strings.
  470. Compiled in errors such as the use of strings that
  471. are not null terminated tend to result in core files.
  472. .SH FILES
  473. /usr/local/lib/libsrtunq.a
  474. .br
  475. /usr/include/local/srtunq.h
  476. .SH SEE ALSO
  477. malloc(3), qsort(3)
  478. .SH AUTHOR
  479. Stephen Uitti, PUCC
  480. .SH BUGS
  481. Likely.
  482. SHAR_EOF
  483. if test 3745 -ne "`wc -c srtunq.3l`"
  484. then
  485. echo shar: error transmitting srtunq.3l '(should have been 3745 characters)'
  486. fi
  487. chdir ..
  488. cat << \SHAR_EOF > abrv.c
  489. /* abbreviation related routines 
  490.  * Written & hacked by Stephen Uitti, PUCC staff, ach@pucc-j, 1985
  491.  * maketd is copyright (C) Purdue University, 1985
  492.  *
  493.  * Permission is hereby given for its free reproduction and
  494.  * modification for non-commercial purposes, provided that this
  495.  * notice and all embedded copyright notices be retained.
  496.  * Commercial organisations may give away copies as part of their
  497.  * systems provided that they do so without charge, and that they
  498.  * acknowledge the source of the software.
  499.  */
  500.  
  501. #ifdef BSD2_9
  502. #include <sys/types.h>
  503. #endif
  504. #include <stdio.h>
  505. #include <ctype.h>
  506. extern char *malloc();
  507.  
  508. #include "srtunq.h"
  509. #include "abrv.h"
  510. #include "maketd.h"
  511.  
  512. struct srtent abrv;            /* include file abrevs */
  513. char   *abrvtbl[MXABR];            /* translation table strings */
  514. int    abrvlen[MXABR];            /* string lengths (for speed) */
  515.  
  516. /* lngsrt - string length more important than lexicographical compare.
  517.  * return > 0 if b is longer than a.
  518.  * return < 0 if b is shorter than a.
  519.  * if a & b are the same length, return strcmp(a, b), which means
  520.  * that 0 is returned if the strings are THE SAME,
  521.  * if b > a: return > 0
  522.  * if b < a: return < 0
  523.  */
  524. int
  525. lngsrt(a, b)
  526. char *a, *b;
  527. {
  528.     register i;
  529.  
  530.     if ((i = strlen(b) - strlen(a)) != 0)
  531.     return i;
  532.     else
  533.     return strcmp(a, b);
  534. }
  535.  
  536. /* hincl - include header optimizer:
  537.  * Compress multiple leading /'s to just one.
  538.  * Remove leading "./".
  539.  * Doesn't change date, just returns pointer into begining of path.
  540.  */
  541. char *
  542. hincl(p)
  543. register char *p;
  544. {
  545.     if (*p == '/')        /* compress multiple leading /'s */
  546.     while (p[1] == '/')    /* to just one */
  547.         p++;
  548.     if (strncmp("./", p, 2) == 0) {
  549.     p += 2;            /* leading "./" can confuse make */
  550.     while (*p == '/')    /* don't change ".//a.h" to "/a.h" */
  551.         p++;
  552.     }
  553.     return p;
  554. }
  555.  
  556. /* srchincl - search line for make defines of A-Z
  557.  * Put entries into abrvtbl.
  558.  */
  559. void
  560. srchincl(p)
  561. register char *p;
  562. {
  563.     register char *q, *r;
  564.     register i;
  565.  
  566.     if (shortincl && *p != '\0') {
  567.     while (*p == SPC || *p == '\t')
  568.         p++;        /* ignore white space */
  569.     q = p;            /* what letter */
  570.     if (isupper(*p)) {    /* A-Z, for now */
  571.         p++;
  572.         while (*p == SPC || *p == '\t')
  573.         p++;        /* ignore white space */
  574.         if (*p++ == '=') {
  575.         while (*p == SPC || *p == '\t')
  576.             p++;
  577.         if ((i = strlen(p)) != 0) {
  578.             if ((r = malloc((unsigned)(i + 1))) == NULL)
  579.             err("Out of memory in define search");
  580.             if (abrvtbl[*q - 'A'])
  581.             fprintf(stderr, "%s: warning - %c redefined in %s\n",
  582.                 prgnm, *q, makename);
  583.             abrvtbl[*q - 'A'] = r;
  584.             while (*p != '\0' && *p != '#' && *p != '\n')
  585.             *r++ = *p++;
  586.             *r = '\0';    /* null terminate result */
  587.         }        /* if non-null string */
  588.         }            /* if = */
  589.     }            /* if A-Z */
  590.     }                /* if shortinclude & string */
  591. }
  592.  
  593. /* abrvsetup - set up abrev table, spit out the abrevs.     Use
  594.  * any A-Z definitions found in Makefile, no duplicates.  Add
  595.  * /usr/include & /usr/include/sys if "all" dependencies are
  596.  * being generated (including /usr/include based files).
  597.  * Try to use I=/usr/include and S=/usr/include/sys, but don't
  598.  * make a stink about it.
  599.  */
  600. void
  601. abrvsetup()
  602. {
  603.     register i;                /* temp */
  604.     register char *p;            /* temp */
  605.     register slot;            /* slot search point */
  606.     register j;                /* temp */
  607.     static abrdone = FALSE;        /* do this only once */
  608.     register flushi = FALSE;        /* print I=.. */
  609.     register flushs = FALSE;        /* print S=.. */
  610.     static char *istring = "I=/usr/include";
  611.     static char *sstring = "S=/usr/include/sys";
  612.  
  613.     if (abrdone)
  614.     return;
  615.     if (shortincl) {
  616.     abrdone = TRUE;            /* we've done this */
  617.     /* add /usr/include/sys, /usr/include if not already there */
  618.     if (alldep) {
  619.         if (abrvtbl['S'-'A'] == NULL) {
  620.         flushs = TRUE;
  621.         srchincl(sstring);
  622.         } else if ((p = srtin(&abrv, &sstring[2], lngsrt)) != NULL)
  623.         fprintf(stderr, "%s: %s - %s\n", prgnm, p, &sstring[2]);
  624.         if (abrvtbl['I'-'A'] == NULL) {
  625.         flushi = TRUE;
  626.         srchincl(istring);
  627.         } else if ((p = srtin(&abrv, &istring[2], lngsrt)) != NULL)
  628.         fprintf(stderr, "%s: %s - %s\n", prgnm, p, &istring[2]);
  629.     }
  630.     if (!replace) {            /* no new defines with replace */
  631.         srtgti(&abrv);        /* init tree traversal */
  632.         slot = 0;            /* start at bgn */
  633.         while ((p = srtgets(&abrv)) != NULL) {
  634.         j = strlen(p);
  635.         for (i = 0; i < MXABR; i++) { /* look for this definition */
  636.             if (abrvtbl[i] == NULL)
  637.             continue;    /* check non-null entries */
  638.             if (*abrvtbl[i] == '\0')
  639.             continue;    /* check non-null entries */
  640.             if (strcmp(p, abrvtbl[i]) == 0)
  641.             break;        /* exact match found */
  642.             else if (strlen(abrvtbl[i]) == j + 1 &&
  643.             strncmp(p, abrvtbl[i], j) == 0 &&
  644.                 abrvtbl[i][j] == '/')
  645.             break;        /* match of "p/" found */
  646.         }
  647.         if (i == MXABR) {    /* not found */
  648.             for (i = slot; i < MXABR; i++) /* find free slot */
  649.             if (abrvtbl[i] == NULL)
  650.                 break;
  651.             if (i < MXABR) {    /* free slot found */
  652.         /*     if (!usestdout && !replace) */
  653.                 fprintf(makefd, "%c=%s\n", 'A' + i, p);
  654.             abrvtbl[i++] = p;
  655.             slot = i;    /* reduce free slot search time */
  656.             }
  657.         }            /* if not found */
  658.         }                /* while */
  659.     }                /* if !replace */
  660.     if (flushi && !usestdout && !replace)
  661.         fprintf(makefd, "%s\n", istring);
  662.     if (flushs && !usestdout && !replace)
  663.         fprintf(makefd, "%s\n", sstring);
  664.     for (i = 0; i < MXABR; i++) {    /* set up string lengths */
  665.         if (abrvtbl[i] == NULL) {
  666.         abrvlen[i] = 0;
  667.         } else {
  668.         abrvlen[i] = strlen(abrvtbl[i]);
  669.         if (verbose)
  670.             fprintf(stderr, "%s: %c='%s'\n",
  671.             prgnm, i + 'A', abrvtbl[i]);
  672.         }                /* if */
  673.     }                /* for */
  674.     }                    /* if */
  675. }
  676.  
  677. /* findabr - find an abbreviation in abrvtbl for string p (if any).
  678.  * if multiple abbreations work, use longest.
  679.  * (ie: /usr/include & /usr/include/sys; use /usr/include/sys)
  680.  * if found, return index
  681.  * else: MXABR
  682.  * Do not match abbreviations of less than 3 characters.
  683.  */
  684. int
  685. findabr(p)
  686. register char *p;            /* string pointer */
  687. {
  688.     register i;                /* for index */
  689.     register j;                /* found index */
  690.  
  691.     for (i = 0, j = MXABR; i < MXABR; i++)
  692.     if (abrvlen[i] > 2)        /* changing "." to $A is evil */
  693.         if (strncmp(abrvtbl[i], p, abrvlen[i]) == 0)
  694.         if (j == MXABR || (abrvlen[i] > abrvlen[j]))
  695.             j = i;
  696.     return j;
  697. }
  698. SHAR_EOF
  699. if test 6197 -ne "`wc -c abrv.c`"
  700. then
  701. echo shar: error transmitting abrv.c '(should have been 6197 characters)'
  702. fi
  703. cat << \SHAR_EOF > abrv.h
  704. /* include srtunq.h first */
  705.  
  706. #define MXABR 26            /* upper case chars used */
  707. extern char    *abrvtbl[];        /* translation table strings */
  708. extern int    abrvlen[];        /* string lengths (for speed) */
  709. extern SRTUNQ    abrv;            /* include file abrevs */
  710.  
  711. /* abbreviation fucntions */
  712. extern int    lngsrt();        /* compare function for abrevs */
  713. extern char    *hincl();        /* optimizer for include paths */
  714. extern void    srchincl();        /* find [A-Z] makefile defines */
  715. extern void    abrvsetup();        /* create abrvs, write them */
  716. extern int    findabr();        /* find longest abrv */
  717. SHAR_EOF
  718. if test 544 -ne "`wc -c abrv.h`"
  719. then
  720. echo shar: error transmitting abrv.h '(should have been 544 characters)'
  721. fi
  722. cat << \SHAR_EOF > breakargs.c
  723. /* breakargs - break a string into a string vector for execv.
  724.  * Returns NULL if can't malloc space for vector, else vector.
  725.  * Note, when done with the vector, mearly "free" the vector.
  726.  * Written by Stephen Uitti, PUCC, Nov '85 for the new version
  727.  * of "popen" - "nshpopen", that doesn't use a shell.
  728.  * (used here for the as filters, a newer option).
  729.  *
  730.  * breakargs is copyright (C) Purdue University, 1985
  731.  *
  732.  * put in a fix for cmds lines with "string string" in them
  733.  * Mon Aug 25 13:34:27 EST 1986 (ksb)
  734.  *
  735.  * Permission is hereby given for its free reproduction and
  736.  * modification for non-commercial purposes, provided that this
  737.  * notice and all embedded copyright notices be retained.
  738.  * Commercial organisations may give away copies as part of their
  739.  * systems provided that they do so without charge, and that they
  740.  * acknowledge the source of the software.
  741.  */
  742. #ifdef BSD2_9
  743. #include <sys/types.h>
  744. #endif
  745. #include <stdio.h>            /* for nothing, really */
  746. #define SPC '\040'            /* ascii space */
  747.  
  748. char *
  749. mynext(pch)
  750. register char *pch;
  751. {
  752.     register int fQuote;
  753.  
  754.     for (fQuote = 0; (*pch != '\000' && *pch != SPC && *pch != '\t')||fQuote; ++pch) {
  755.         if ('\\' == *pch) {
  756.             continue;
  757.         }
  758.         switch (fQuote) {
  759.         default:
  760.         case 0:
  761.             if ('"' == *pch) {
  762.                 fQuote = 1;
  763.             } else if ('\'' == *pch) {
  764.                 fQuote = 2;
  765.             }
  766.             break;
  767.         case 1:
  768.             if ('"' == *pch)
  769.                 fQuote = 0;
  770.             break;
  771.         case 2:
  772.             if ('\'' == *pch)
  773.                 fQuote = 0;
  774.             break;
  775.         }
  776.     }
  777.     return pch;
  778. }
  779.  
  780. char **
  781. breakargs(cmd)
  782. char *cmd;
  783. {
  784.     register char *p;        /* tmp                */
  785.     register char **v;        /* vector of commands returned    */
  786.     register unsigned sum;        /* bytes for malloc        */
  787.     register int i;            /* number of args        */
  788.     register char *s;        /* save old position        */
  789.     char *malloc(), *strcpy();
  790.  
  791.     p = cmd;
  792.     while (*p == SPC || *p == '\t')
  793.         p++;
  794.     cmd = p;            /* no leading spaces        */
  795.     sum = sizeof(char *);
  796.     i = 0;
  797.     while (*p != '\0') {        /* space for argv[];        */
  798.         ++i;
  799.         s = p;
  800.         p = mynext(p);
  801.         sum += sizeof(char *) + 1 + (unsigned)(p - s);
  802.         while (*p == SPC || *p == '\t')
  803.             p++;
  804.     }
  805.     ++i;
  806.     /* vector starts at v, copy of string follows NULL pointer */
  807.     v = (char **)malloc(sum+1);
  808.     if (v == NULL)
  809.         return (char **)NULL;
  810.     p = (char *)v + i * sizeof(char *); /* after NULL pointer */
  811.     i = 0;                /* word count, vector index */
  812.     while (*cmd != '\0') {
  813.         v[i++] = p;
  814.         s = cmd;
  815.         cmd = mynext(cmd);
  816.         if (*cmd != '\0')
  817.             *cmd++ = '\0';
  818.         strcpy(p, s);
  819.         p += strlen(p);
  820.         ++p;
  821.         while (*cmd == SPC || *cmd == '\t')
  822.             ++cmd;
  823.     }
  824.     v[i] = (char *)NULL;
  825.     return v;
  826. }
  827. SHAR_EOF
  828. if test 2529 -ne "`wc -c breakargs.c`"
  829. then
  830. echo shar: error transmitting breakargs.c '(should have been 2529 characters)'
  831. fi
  832. cat << \SHAR_EOF > maketd.c
  833. /* maketd - MAKE Transitive Dependencies.
  834.  * (This is a lie - the dependencies are not transitive, but "all"
  835.  * dependencies are correctly made.)
  836.  *
  837.  * Based loosely on a shell script by Stephan Bechtolsheim, svb@purdue
  838.  * Other Makefile related features have been added or merged in from
  839.  * other programs.
  840.  *
  841.  * Written & hacked by Stephen Uitti, PUCC staff, ach@pucc-j, 1985
  842.  * maketd is copyright (C) Purdue University, 1985
  843.  *
  844.  * removed some of Steve's good, but unnecessary, options in favor
  845.  * of more compile time flags & better implicit rules in the makefile
  846.  * dinked: -q -e -E -k
  847.  * Kevin S Braunsdorf, PUCC UNIX Group 1986    (ksb@j.cc.purdue.edu)
  848.  *
  849.  * Permission is hereby given for its free reproduction and
  850.  * modification for non-commercial purposes, provided that this
  851.  * notice and all embedded copyright notices be retained.
  852.  * Commercial organisations may give away copies as part of their
  853.  * systems provided that they do so without charge, and that they
  854.  * acknowledge the source of the software.
  855.  */
  856. #include <sys/types.h>
  857. #include <sys/param.h>
  858. #include <sys/file.h>            /* for access */
  859. #ifdef BSD2_9
  860. #include <ndir.h>            /* for MAXPATHLEN, MAXNAMLEN */
  861. #endif
  862. #ifdef BSD4_2
  863. #include <sys/dir.h>            /* for MAXNAMLEN in 4.2 */
  864. #endif
  865. #include <ctype.h>            /* for isupper */
  866. #include <stdio.h>
  867. extern char *rindex(), *index(), *strcat(), *strcpy();
  868.  
  869. #include "srtunq.h"
  870. #include "abrv.h"
  871. #include "nshpopen.h"
  872. #include "maketd.h"
  873.  
  874. #ifndef CPP
  875. #define CPP    "/lib/cpp "
  876. #endif CPP not in Makefile
  877.  
  878. /* forward functions */
  879. void    msoio();            /* open output file */
  880. void    rdwr();                /* read old Makefile into new */
  881. void    mkdepend();            /* does the real work */
  882.  
  883. /* globals */
  884. char *prgnm;                /* our program name        */
  885. FILE *makefd;                /* makefile stream        */
  886. int    alldep = FALSE;            /* -a all - /usr/include too    */
  887. char   *targetname = NULL;        /* -t target name for next file */
  888. char   *destsuffix = ".o";        /* -s suffix for targets    */
  889. int    header = TRUE;            /* print header & trailer    */
  890. int    usestdout = FALSE;        /* -d use stdout for makefile    */
  891. int    forcehead = FALSE;        /* -f force header/trailer    */
  892. int    makenseen = FALSE;        /* output file has been specified */
  893. char   *makename = "makefile";        /* -m default file for edit    */
  894. int    backedup = FALSE;        /* for interupt recovery    */
  895. char    backupfn[MAXNAMLEN+1];        /* backup file name        */
  896. int    ismakeopen = FALSE;        /* if the output file is open    */
  897. char    objpath[MAXPATHLEN+1];        /* -o prepended to .o's        */
  898. int    nonlocalo = FALSE;        /* -nonlocalo objects in source dir */
  899. int    replace = FALSE;        /* -r replace depends in Makefile */
  900. char    cppflags[BUFSIZ];        /* -D, -I, -U flags to pass to cpp */
  901. int    shortincl = TRUE;        /* -x do abreviations        */
  902. int    verbose = FALSE;        /* -v verbage for the debugger    */
  903. static char   sopts[] = "abdfhrxv";    /* single char opts        */
  904. static SRTUNQ u;            /* unique include files        */
  905.  
  906. char   usage[] =
  907. "Usage: maketd [-a -b -d -f -h -mMAKEFILE -nonlocalo -oDIR -r -sSUFFIX\n\
  908.  -tTARGETNAME -x -v -Iincludedir -Ddefine -Uundefine file...]\n";
  909. char   helptext[] =
  910. "-a\tdo all dependencies, including /usr/include\n\
  911. -b\tgenerate binary, rather than object related dependencies\n\
  912. -d\tdependencies to stdout, rather than Makefile\n\
  913. -f\tforce header/trailer (use with -d)\n\
  914. -h\thelp (this text)\n\
  915. -m\tspecify MAKEFILE for edit\n\
  916. -nonlocalo Objects live in source directory\n\
  917. -o\tprepend DIR to target: DIR/a.o: foo.h\n\
  918. -r\treplace dependencies for a target\n\
  919. -s\tchange suffix target's SUFFIX: a.SUFFIX: foo.h\n\
  920. -t\tchange target's basename: TARGET.o: foo.h\n\
  921. -x\tdon't abbreviate includes\n\
  922. -v\tprint extra verbose (debug) output to stderr\n\
  923. -I\tspecify include directory, as in /lib/cpp\n\
  924. -D\tspecify defines, as in /lib/cpp\n\
  925. -U\tspecify undefines, as in /lib/cpp\n";
  926.  
  927. char deplin[] = "# DO NOT DELETE THIS LINE - make depend DEPENDS ON IT\n";
  928. char searchdep[] = "# DO NOT DELETE THIS LINE";
  929. char trailer[] = "\n# *** Do not add anything here - It will go away. ***\n";
  930.  
  931. /* some init & argv parsing */
  932. main(argc, argv)
  933. register int argc;
  934. register char **argv;
  935. {
  936.     register a;                /* argv subscript        */
  937.     register i;                /* tmp                */
  938.     register len;            /* length of current argument    */
  939.     register files = FALSE;        /* files ever seen        */
  940.     register char *q;            /* tmp                */
  941.  
  942.     /* prgnm = program name, for error printing */
  943.     if ((prgnm = rindex(argv[0], '/')) == NULL)
  944.     prgnm = argv[0];
  945.     else
  946.     prgnm++;
  947.     catchsig();                /* init signal traps */
  948.     srtinit(&abrv);            /* init abbreviations tree */
  949.     for (a = 1; a < argc; a++) {    /* argv prepass: find all -I's */
  950.     if (argv[a][0] == '-' && argv[a][1] == 'I' && strlen(&argv[a][2]) > 2)
  951.         if ((q = srtin(&abrv, hincl(&argv[a][2]), lngsrt)) != NULL)
  952.         fprintf(stderr, "%s: %s - %s\n", prgnm, q, &argv[a][2]);
  953.     }
  954.     cppflags[0] = '\0';            /* terminate cpp flags string */
  955.     objpath[0] = '\0';            /* init object path */
  956.     srtinit(&u);            /* init sorting database tag */
  957.     for (a = 1; a < argc; a++) {
  958.     len = strlen(argv[a]);
  959.     if (argv[a][0] == '-' && len > 2 && index(sopts, argv[a][1]) != NULL)
  960.         err("options must be listed seperately - '%s'\n", argv[a]);
  961.     if (len > 1 && argv[a][0] == '-') {
  962.         switch (argv[a][1]) {
  963.         case 'D':            /* /lib/cpp flags to pass */
  964.         case 'I':
  965.         case 'U':
  966.         if (strlen(cppflags) + strlen(argv[a]) + 2 > BUFSIZ)
  967.             err("too many cpp flags - buffer overflow");
  968.         strcat(cppflags, argv[a]);
  969.         strcat(cppflags, " ");    /* add a space separator */
  970.         break;
  971.         case 'a':            /* /usr/include deps too */
  972.         alldep = TRUE;
  973.         break;
  974.         case 'b':            /* target has no suffix */
  975.         destsuffix = "";
  976.         break;
  977.         case 'd':            /* don't edit Makefile */
  978.         if (ismakeopen)
  979.             err("Makefile already open, -d must precede filenames");
  980.         if (makenseen)
  981.             err("Conflict - check -d and -m options");
  982.         makenseen = TRUE;
  983.         usestdout = TRUE;
  984.         if (!forcehead)
  985.             header = FALSE;    /* don't do header & trailer */
  986.         break;
  987.         case 'f':            /* force header/trailer */
  988.         forcehead = TRUE;
  989.         header = TRUE;
  990.         break;
  991.         case 'h':            /* help */
  992.         fputs(usage, stdout);
  993.         fputs(helptext, stdout);
  994.         exit(0);
  995.         break;
  996.         case 'm':            /* specify makefile name for edit */
  997.         if (ismakeopen)
  998.             err("Makefile already open, -m must precede filenames");
  999.         if (makenseen)
  1000.             err("Conflict, check -m and -d options.");
  1001.         if (strlen(makename) == 0)
  1002.             err("-m option requires file name.");
  1003.         makenseen = TRUE;
  1004.         makename = &argv[a][2];
  1005.         break;
  1006.         case 'n':            /* objects reside with sources */
  1007.         if (strcmp("nonlocalo", &argv[a][1]) != 0)
  1008.             err("bad -n option"); /* what a crock of an option */
  1009.         if (objpath[0] != '\0')
  1010.             err("nonlocalo conflict - check -o's");
  1011.         nonlocalo = TRUE;
  1012.         break;
  1013.         case 'o':
  1014.         if (nonlocalo)
  1015.             err("object path conflict - check -o's and -nonlocalo's");
  1016.         strcpy(objpath, &argv[a][2]);
  1017.         i = strlen(objpath);
  1018.         if (i == 0)
  1019.             err("-o requires path string.");
  1020.         if (i >= MAXPATHLEN)
  1021.             err("Object path too long: max is %d.", MAXPATHLEN);
  1022.         if (objpath[i - 1] != '/')
  1023.             strcat(objpath, "/");
  1024.         break;
  1025.         case 'r':            /* replace mode */
  1026.         if (ismakeopen)
  1027.             err("Makefile already open, -r must precede filenames");
  1028.         replace = TRUE;
  1029.         break;
  1030.         case 's':            /* destination suffix */
  1031.         destsuffix = &argv[a][2];
  1032.         break;
  1033.         case 't':            /* set target's basename */
  1034.         targetname = &argv[a][2];
  1035.         if (len <= 2)
  1036.             err("target option requires name.");
  1037.         break;
  1038.         case 'v':            /* user wants to hear noise */
  1039.         verbose = TRUE;
  1040.         break;
  1041.         case 'x':            /* don't abbrev. */
  1042.         if (files)
  1043.             err("-x option must preceed all files.");
  1044.         shortincl = FALSE;
  1045.         break;
  1046.         default:
  1047.         err("Unknown option %s.", argv[a]);
  1048.         }                /* end switch */
  1049.     } else {            /* must be a filename */
  1050.         if (verbose)
  1051.         fprintf(stderr, "%s: working on %s.\n", prgnm, argv[a]);
  1052.         files = TRUE;        /* at least one file seen */
  1053.         if (replace && a != argc - 1)
  1054.         err("Only one file allowed with -r (edit aborted)");
  1055.         mkdepend(argv[a]);        /* file to process */
  1056.         targetname = NULL;        /* affect only one file */
  1057.     }                /* if option */
  1058.     }                    /* for argv */
  1059.     if (ismakeopen && header)
  1060.     fputs(trailer, makefd);        /* do not delete... */
  1061. #if    DEL_BACKUP
  1062.     if (backedup)
  1063.     if (unlink(backupfn))
  1064.         err("Can't delete backup file %s on completion", backupfn);
  1065. #endif    DEL_BACKUP
  1066.     if (!files)
  1067.     err("No files to process, use -h for full help.\n%s", usage);
  1068.     exit(0);                /* exit status - good */
  1069. }
  1070.  
  1071. /* msoio - Make Sure Output Is Open.
  1072.  * Interacts strongly via globals: makefd, backedup, backupfn, makename,
  1073.  * header, ismakeopen
  1074.  */
  1075. void
  1076. msoio(targ)
  1077. char *targ;                /* if -r, is target name */
  1078. {
  1079.     FILE *tmpfd;            /* temp file desc for -d */
  1080.     char buf[BUFSIZ];            /* for reading the makefile */
  1081.  
  1082.     if (ismakeopen)
  1083.     return;
  1084.     ismakeopen = TRUE;            /* will be: all errs are fatal */
  1085.     if (usestdout) {
  1086.     makefd = stdout;
  1087.     if (header) {
  1088.         fputc('\n', makefd);    /* one blank line */
  1089.         fputs(deplin, makefd);    /* the first line */
  1090.     }
  1091.     /* scan "makefile" or "Makefile" for include defines */
  1092.     if (access(makename, R_OK) != 0) {
  1093.         makename[0] = 'M';        /* try Makefile */
  1094.         if (access(makename, R_OK) != 0)
  1095.         return;            /* just punt */
  1096.     }
  1097.     if ((tmpfd = fopen(makename, "r")) == NULL)
  1098.         return;            /* just punt */
  1099.     while (fgets(buf, BUFSIZ, tmpfd) != NULL)
  1100.         srchincl(buf);        /* scan whole file */
  1101.     fclose(tmpfd);
  1102.     return;
  1103.     }                    /* ... if standard out */
  1104. /* !makenseen means (default) try "makefile" then "Makefile" */
  1105.     if (!makenseen && access(makename, F_OK) != 0)
  1106.     makename[0] = 'M';        /* try Makefile */
  1107. /* side effect: "Makefile" will be created if neither exist */
  1108.     if (access(makename, F_OK) == 0) {    /* if makefile exits */
  1109.     strcpy(backupfn, makename);    /* get rid of .bak */
  1110.     strcat(backupfn, ".bak");
  1111.     if (access(backupfn, F_OK) == 0) {
  1112.         if (unlink(backupfn))
  1113.         err("Can't remove %s for pre-edit\n", backupfn);
  1114.     }
  1115.     if (link(makename, backupfn))    /* mv makefile to .bak */
  1116.         err("Can't link %s to %s.", backupfn, makename);
  1117.     backedup = TRUE;        /* for interupt status */
  1118.     if (unlink(makename))
  1119.         err("Can't unlink %s during rename.", makename);
  1120.     } else {
  1121.     backupfn[0] = '\0';        /* no copy (no makefile) */
  1122.     }
  1123.     if ((makefd = fopen(makename, "w")) == NULL)
  1124.     err("Can't open output file '%s' for write.", makename);
  1125.     if (backupfn[0] != '\0')        /* if no .bak file - done */
  1126.     rdwr(targ);            /* read/write Makefile */
  1127.     else
  1128.     fputs(deplin, makefd);        /* must start with this */
  1129. }
  1130.  
  1131. /* create beginging of new Makefile by reading old one */
  1132. void
  1133. rdwr(targ)
  1134. char *targ;
  1135. {
  1136.     register FILE *oldfd;        /* file pointer for .old */
  1137.     char rwbuf[BUFSIZ];            /* temp for read/write */
  1138.     register tlen;            /* targ length */
  1139.     register puntln = FALSE;        /* punt current line? */
  1140.     register contln = FALSE;        /* previous line ended with '\'? */
  1141.     register blankln = 0;        /* number of blank lines seen */
  1142.     register srchsn = FALSE;        /* search line seen? */
  1143.  
  1144.     if ((oldfd = fopen(backupfn, "r")) == NULL)
  1145.     err("Can't open backup copy of %s\n", makename);
  1146.     tlen = strlen(targ);
  1147.     while (fgets(rwbuf, BUFSIZ, oldfd) != NULL) { /* until EOF */
  1148.     if (!srchsn) {
  1149.         if (strncmp(searchdep, rwbuf, (sizeof searchdep) - 1) == 0) {
  1150.         srchsn = TRUE;
  1151.         fputs(deplin, makefd);    /* re-write this line */
  1152.         if (!replace)
  1153.             break;
  1154.         continue;        /* don't print this line */
  1155.         }
  1156.     } else {
  1157.         if (strcmp("\n", rwbuf) == 0) {
  1158.         if (!puntln)
  1159.             blankln++;
  1160.         contln = FALSE;
  1161.         puntln = FALSE;
  1162.         continue;        /* don't output this blank line */
  1163.         }
  1164.         if (!contln) {
  1165.         if (strncmp(targ, rwbuf, tlen) == 0)
  1166.             puntln = TRUE;
  1167.         else if (strcmp(&trailer[1], rwbuf) == 0)
  1168.             puntln = TRUE;
  1169.         }
  1170.         if (lastlnch(rwbuf) == '\\')
  1171.         contln = TRUE;
  1172.         else
  1173.         contln = FALSE;
  1174.     }                /* if srchsn */
  1175.     if (!puntln) {
  1176.         srchincl(&rwbuf[0]);    /* search this line for defines */
  1177.         if (blankln != 0) {        /* compress mult blank lines to one */
  1178.         putc('\n', makefd);
  1179.         blankln = 0;
  1180.         }
  1181.         fputs(rwbuf, makefd);    /* non targ lines */
  1182.     }
  1183.     }                    /* while fgets */
  1184.     if (!srchsn)            /* deplin never found */
  1185.     fputs(deplin, makefd);        /* so write one */
  1186.     (void) fclose(oldfd);        /* close the .old file for gigles */
  1187. }
  1188.  
  1189. #define MAXCOL 78            /* output width max for makefile */
  1190.  
  1191. /* mkdepend - name is historical, but does the "real work" */
  1192. void
  1193. mkdepend(infile)
  1194. char *infile;
  1195. {
  1196.     register char *p;            /* temp pointer */
  1197.     register char *q;            /* temp pointer */
  1198.     register char *r;            /* temp pointer */
  1199.     register FILE *cppfd;        /* file desc for /lib/cpp */
  1200.     char buf[BUFSIZ];            /* temp buff */
  1201.     char basename[MAXNAMLEN+1];        /* just the file name */
  1202.     register oplen;            /* length target & path */
  1203.     register le;            /* length of current output line */
  1204.     register char *targ;        /* target's name */
  1205.     register i;                /* tmp for index */
  1206.     register firstln;            /* first line of a list */
  1207.  
  1208.     if ((p = rindex(infile, '/')) == NULL) /* past path */
  1209.     p = infile;
  1210.     else
  1211.     p++;
  1212.     if (nonlocalo && p != infile) {    /* objpath = source path */
  1213.     for (q = objpath, r = infile; r < p;)
  1214.         *q++ = *r++;
  1215.     *q = '\0';            /* null terminate */
  1216.     }
  1217.     strcpy(basename, p);
  1218.     if ((p = rindex(basename, '.')) != NULL)
  1219.     *p = '\0';            /* remove trailing ".*" */
  1220.     if (targetname != NULL)        /* set up target's name */
  1221.     targ = targetname;
  1222.     else
  1223.     targ = basename;
  1224.     if (makename == NULL) {
  1225.     makename = "Makefile";
  1226.     if (access(makename, F_OK) != 0)
  1227.         makename[0] = 'm';        /* not a real check */
  1228.     }
  1229.     msoio(targ);            /* Make Sure Output Is Open */
  1230.     abrvsetup();            /* create abrev table, write defs. */
  1231.     if (access(infile, R_OK) != 0) {
  1232.     fprintf(stderr, "%s: Can't open input file '%s', skipped.\n",
  1233.         prgnm, infile);
  1234.     return;
  1235.     }
  1236.     (void)strcpy(buf, CPP);    /* build cpp cmd line */
  1237. #if CPP_M
  1238.     strcat(buf, "-M ");        /* -M flag - does dependencies */
  1239. #endif
  1240.     if (strlen(buf) + strlen(cppflags) + strlen(infile) + 1 > BUFSIZ)
  1241.     err("cpp command line buffer overflow");
  1242.     (void)strcat(buf, cppflags);    /* add command flags */
  1243.     (void)strcat(buf, infile);        /* add file name */
  1244.     srtfree(&u);            /* init insertion sorter */
  1245.     if (verbose)
  1246.     fprintf(stderr, "%s: cpp line is '%s'\n", prgnm, buf);
  1247.     if ((cppfd = nshpopen(buf, "r")) == NULL)
  1248.     err("Can't open pipe for %s", buf);
  1249. #if CPP_M
  1250.      while (fgets(buf, BUFSIZ, cppfd) != NULL) {
  1251.      if ((p = index(buf, ':')) == NULL)
  1252.          err("cpp -M format error - colon");
  1253.      p++;            /* pass colon */
  1254.      if (*p++ != SPC)
  1255.          err("cpp -M format error - space");
  1256.      p = hincl(p);        /* skip any uglies in include path */
  1257.      if (!alldep && strncmp("/usr/include", p, 12) == 0)
  1258.          continue;        /* ignore /usr/include... stuff */
  1259.      if (index(p, '\n') != NULL) /* replace newline with EOS */
  1260.          *index(p, '\n') = '\0';
  1261.      if ((q = srtin(&u, p, (int (*)())0)) != NULL) /* insert into list */
  1262.          fprintf(stderr, "%s: %s - %s\n", prgnm, q, p); /* warning */
  1263.      }
  1264. #else
  1265.      while (fgets(buf, BUFSIZ, cppfd) != NULL) {
  1266.      if (buf[0] != '#')        /* must start with '#' */
  1267.          continue;
  1268.      if ((p = index(buf, '"')) == NULL) /* find first double quote */
  1269.          continue;
  1270.      p++;
  1271.      p = hincl(p);        /* skip any uglies in include path */
  1272.      if (index(p, '"') != NULL)    /* terminate the file name */
  1273.          *index(p, '"') = '\0';
  1274.      if (!alldep && strncmp("/usr/include", p, 12) == 0)
  1275.          continue;        /* ignore /usr/include... stuff */
  1276.      if ((q = srtin(&u, p, (int (*)())0)) != NULL) /* insert into list */
  1277.          fprintf(stderr, "%s: %s - %s\n", prgnm, q, p); /* warning */
  1278.      }
  1279. #endif
  1280.     srtgti(&u);                /* init for srtgets */
  1281.     /* 2 for colon space */
  1282.     oplen = strlen(objpath) + strlen(targ) + strlen(destsuffix) + 2;
  1283.     le = MAXCOL;            /* force new line output */
  1284.     firstln = TRUE;            /* first line of a file entry */
  1285.     while ((p = srtgets(&u)) != NULL) { /* write out the entries */
  1286.     if (shortincl)
  1287.         if ((i = findabr(p)) != MXABR) /* i = found index or MXABR */
  1288.         p += abrvlen[i] - 2;
  1289.     if (le + strlen(p) >= MAXCOL) {
  1290.         if (firstln) {
  1291.         le = oplen;
  1292.         fprintf(makefd, "\n%s%s%s: ", objpath, targ, destsuffix);
  1293.         firstln = FALSE;
  1294.         } else {
  1295.         le = 8;
  1296.         fprintf(makefd, " \\\n\t");
  1297.         }
  1298.     } else {
  1299.         fputc(SPC, makefd);
  1300.     }
  1301.     if (shortincl && i != MXABR) {
  1302.         fprintf(makefd, "$%c", 'A' + i);
  1303.         p += 2;            /* right place */
  1304.         le += 2;
  1305.     }
  1306.     fputs(p, makefd);
  1307.     le += 1 + strlen(p);
  1308.     }
  1309.     fputc('\n', makefd);        /* end with newline */
  1310.     nshpclose(cppfd);            /* end of that file */
  1311. }
  1312. SHAR_EOF
  1313. if test 16381 -ne "`wc -c maketd.c`"
  1314. then
  1315. echo shar: error transmitting maketd.c '(should have been 16381 characters)'
  1316. fi
  1317. cat << \SHAR_EOF > maketd.h
  1318. #define TRUE    1
  1319. #define FALSE    0
  1320. #define SPC    '\040'
  1321.  
  1322. /* globals */
  1323. extern char    *prgnm;            /* the progs called name */
  1324. extern int    alldep;            /* -a all - /usr/include too */
  1325. extern int    usestdout;        /* -d use stdout for makefile */
  1326. extern FILE    *makefd;        /* file desc. for output file */
  1327. extern char    *makename;        /* -m default file for edit */
  1328. extern int    backedup;        /* for interupt recovery */
  1329. extern char    backupfn[];        /* backup file name */
  1330. extern int    replace;        /* -r replace depends in Makefile */
  1331. extern int    shortincl;        /* -x do abreviations */
  1332. extern int    verbose;        /* -v verbage for the debugger */
  1333. extern char    usage[];        /* for error output */
  1334.  
  1335. extern void    err();            /* error msg, exit cleanly */
  1336. extern void    errrec();        /* exit cleanly - also signal trap */
  1337. extern char    lastlnch();        /* last char in line (not \n) */
  1338. SHAR_EOF
  1339. if test 809 -ne "`wc -c maketd.h`"
  1340. then
  1341. echo shar: error transmitting maketd.h '(should have been 809 characters)'
  1342. fi
  1343. cat << \SHAR_EOF > misc.c
  1344. /* Written & hacked by Stephen Uitti, PUCC staff, ach@pucc-j, 1985
  1345.  * maketd is copyright (C) Purdue University, 1985
  1346.  *
  1347.  * Permission is hereby given for its free reproduction and
  1348.  * modification for non-commercial purposes, provided that this
  1349.  * notice and all embedded copyright notices be retained.
  1350.  * Commercial organisations may give away copies as part of their
  1351.  * systems provided that they do so without charge, and that they
  1352.  * acknowledge the source of the software.
  1353.  */
  1354.  
  1355. #ifdef BSD2_9
  1356. #include <sys/types.h>
  1357. #include <signal.h>
  1358. #endif
  1359. #ifdef BSD4_2
  1360. #include <sys/signal.h>
  1361. #endif
  1362. #include <stdio.h>
  1363.  
  1364. #include "maketd.h"
  1365.  
  1366. /* VARARGS */
  1367. /* print and error and exit */
  1368. void
  1369. err(a, b, c, d)
  1370. char *a;                /* the format string, as printf */
  1371. char *b, *c, *d;            /* arguments, as printf */
  1372. {
  1373.     fprintf(stderr, "%s: ", prgnm);
  1374.     fprintf(stderr, a, b, c, d);
  1375.     fprintf(stderr, "\n");
  1376.     errrec();                /* clean up backup file, if any */
  1377.     exit(1);
  1378. }
  1379.  
  1380. /* errrec - error recovery: recover temp file */
  1381. static void
  1382. errrec()
  1383. {
  1384.     if (backedup) {
  1385.     backedup = FALSE;        /* prevent infinite error recursion */
  1386.     unlink(makename);        /* may or may not exist */
  1387.     if (link(backupfn, makename))
  1388.         err("can't link %s to %s during recovery", makename, backupfn);
  1389.     if (unlink(backupfn))
  1390.         err("can't delete %s during recovery", backupfn);
  1391.     err("edit of '%s' aborted - file unchanged.", makename);
  1392.     }
  1393.     exit(1);
  1394. }
  1395.  
  1396. /* signal trap routines, one for each */
  1397. static void
  1398. errhup()
  1399. {
  1400.     fprintf(stderr, "%s: SIGHUP recieved\n", prgnm);
  1401.     errrec();
  1402. }
  1403.  
  1404. static void
  1405. errint()
  1406. {
  1407.     fprintf(stderr, "%s: SIGINT recieved\n", prgnm);
  1408.     errrec();
  1409. }
  1410.  
  1411. static void
  1412. errill()
  1413. {
  1414.     fprintf(stderr, "%s: SIGILL recieved\n", prgnm);
  1415.     errrec();
  1416. }
  1417.  
  1418. static void
  1419. errtrap()
  1420. {
  1421.     fprintf(stderr, "%s: SIGTRAP recieved\n", prgnm);
  1422.     errrec();
  1423. }
  1424.  
  1425. static void
  1426. erriot()
  1427. {
  1428.     fprintf(stderr, "%s: SIGIOT recieved\n", prgnm);
  1429.     errrec();
  1430. }
  1431.  
  1432. static void
  1433. erremt()
  1434. {
  1435.     fprintf(stderr, "%s: SIGEMT recieved\n", prgnm);
  1436.     errrec();
  1437. }
  1438.  
  1439. static void
  1440. errfpe()
  1441. {
  1442.     fprintf(stderr, "%s: SIGFPE recieved\n", prgnm);
  1443.     errrec();
  1444. }
  1445.  
  1446. static void
  1447. errbus()
  1448. {
  1449.     fprintf(stderr, "%s: SIGBUS recieved\n", prgnm);
  1450.     errrec();
  1451. }
  1452.  
  1453. static void
  1454. errsegv()
  1455. {
  1456.     fprintf(stderr, "%s: SIGSEGV recieved\n", prgnm);
  1457.     errrec();
  1458. }
  1459.  
  1460. static void
  1461. errsys()
  1462. {
  1463.     fprintf(stderr, "%s: SIGSYS recieved\n", prgnm);
  1464.     errrec();
  1465. }
  1466.  
  1467. static void
  1468. errpipe()
  1469. {
  1470.     fprintf(stderr, "%s: SIGPIPE recieved\n", prgnm);
  1471.     errrec();
  1472. }
  1473.  
  1474. static void
  1475. erralrm()
  1476. {
  1477.     fprintf(stderr, "%s: SIGALRM recieved\n", prgnm);
  1478.     errrec();
  1479. }
  1480.  
  1481. static void
  1482. errterm()
  1483. {
  1484.     fprintf(stderr, "%s: SIGTERM recieved\n", prgnm);
  1485.     errrec();
  1486. }
  1487.  
  1488. /* catchsig - init signal traps */
  1489. catchsig()
  1490. {
  1491.     signal(SIGHUP, errhup);
  1492.     signal(SIGINT, errint);
  1493.     signal(SIGILL, errill);
  1494.     signal(SIGTRAP, errtrap);
  1495.     signal(SIGIOT, erriot);
  1496.     signal(SIGEMT, erremt);
  1497.     signal(SIGFPE, errfpe);
  1498.     signal(SIGBUS, errbus);
  1499.     signal(SIGSEGV, errsegv);
  1500.     signal(SIGSYS, errsys);
  1501.     signal(SIGPIPE, errpipe);
  1502.     signal(SIGALRM, erralrm);
  1503.     signal(SIGTERM, errterm);
  1504. /* Stock 2.9BSD has all the above, but not as many as 4.2BSD:
  1505.  * Want SIGQUIT to drop core.
  1506.  * Not worrying about:    SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF
  1507.  * cannot be caught: SIGKILL, SIGSTOP
  1508.  * Leaving alone: SIGURG, SIGTSTP, SIGCONT, SIGCHLD, SIGTTIN, SIGTTOU, SIGIO
  1509.  */
  1510. }
  1511.  
  1512. /* lastlnch - return last char before newline or NULL in string */
  1513. char
  1514. lastlnch(p)
  1515. register char *p;
  1516. {
  1517.     register char *q;
  1518.  
  1519.     q = p;
  1520.     while (*p != '\0' && *p != '\n')
  1521.     q = p++;
  1522.     return *q;
  1523. }
  1524. SHAR_EOF
  1525. if test 3572 -ne "`wc -c misc.c`"
  1526. then
  1527. echo shar: error transmitting misc.c '(should have been 3572 characters)'
  1528. fi
  1529. cat << \SHAR_EOF > nshpopen.c
  1530. /* @(#)popen.c    4.5 (Berkeley) 7/6/84
  1531.  * Modified from 4.2, 2.9 BSD popen by Stephen Uitti, PUCC, Nov '85
  1532.  * Doesn't invoke shell, saving time, becoming more secure.
  1533.  * Calls breakargs to break line into command line arguments,
  1534.  * delimited by white space, but ignores globing and quoting
  1535.  * characters.  For use where you don't need shell meta character
  1536.  * expansion or filename globbing.
  1537.  */
  1538. #ifdef BSD2_9
  1539. #include <sys/types.h>
  1540. #endif
  1541. #include <stdio.h>
  1542. #include <signal.h>
  1543.  
  1544. #define    tst(a,b)    (*mode == 'r'? (b) : (a))
  1545. #define    RDR    0
  1546. #define    WTR    1
  1547. #define SPC '\040'            /* ascii space */
  1548.  
  1549. static    int popen_pid[20];
  1550. extern char **environ;
  1551. char **breakargs();
  1552.  
  1553. /* no-shell popen */
  1554. FILE *
  1555. nshpopen(cmd, mode)
  1556. char *cmd;
  1557. char *mode;
  1558. {
  1559.     int p[2];
  1560.     int myside, hisside, pid;
  1561.     char **elist;                /* the execv list */
  1562.  
  1563.     elist = breakargs(cmd);
  1564.     if (pipe(p) < 0)
  1565.         return (NULL);
  1566.     myside = tst(p[WTR], p[RDR]);
  1567.     hisside = tst(p[RDR], p[WTR]);
  1568.     if ((pid = vfork()) == 0) {
  1569.         /* myside and hisside reverse roles in child */
  1570.         close(myside);
  1571.         if (hisside != tst(0, 1)) {    /* 0, 1 => stdin, stdout */
  1572.             dup2(hisside, tst(0, 1));
  1573.             close(hisside);
  1574.         }
  1575.         execve(elist[0], elist, environ);
  1576.         perror("execv");
  1577.         _exit(1);            /* bombed execv, child dies */
  1578.     }
  1579.     free(elist);                /* discard the broken args */
  1580.     if (pid == -1) {
  1581.         close(myside);
  1582.         close(hisside);
  1583.         return (NULL);
  1584.     }
  1585.     popen_pid[myside] = pid;
  1586.     close(hisside);
  1587.     return (fdopen(myside, mode));
  1588. }
  1589.  
  1590. /* close for nshpopen */
  1591. int *
  1592. nshpclose(ptr)
  1593. FILE *ptr;
  1594. {
  1595. #ifdef    BSD4_2
  1596.     int child, pid, status, omask;
  1597.  
  1598.     child = popen_pid[fileno(ptr)];
  1599.     fclose(ptr);
  1600. #define    mask(s)    (1 << ((s)-1))
  1601.     omask = sigblock(mask(SIGINT)|mask(SIGQUIT)|mask(SIGHUP));
  1602.     while ((pid = wait(&status)) != child && pid != -1)
  1603.         /* empty */;
  1604.     (void) sigsetmask(omask);
  1605.     return (int *)(pid == -1 ? -1 : status);
  1606. #else        /* 2.9 BSD, at least */
  1607.     register f, r, (*hstat)(), (*istat)(), (*qstat)();
  1608.     int status;
  1609.  
  1610.     f = fileno(ptr);
  1611.     fclose(ptr);
  1612.     istat = signal(SIGINT, SIG_IGN);
  1613.     qstat = signal(SIGQUIT, SIG_IGN);
  1614.     hstat = signal(SIGHUP, SIG_IGN);
  1615.     while((r = wait(&status)) != popen_pid[f] && r != -1)
  1616.         ;
  1617.     if(r == -1)
  1618.         status = -1;
  1619.     signal(SIGINT, istat);
  1620.     signal(SIGQUIT, qstat);
  1621.     signal(SIGHUP, hstat);
  1622.     return (int *)(status);
  1623. #endif    BSD4_2
  1624. }
  1625. SHAR_EOF
  1626. if test 2253 -ne "`wc -c nshpopen.c`"
  1627. then
  1628. echo shar: error transmitting nshpopen.c '(should have been 2253 characters)'
  1629. fi
  1630. cat << \SHAR_EOF > nshpopen.h
  1631. /* nshpopen defines */
  1632. extern FILE   *nshpopen();        /* open pipe */
  1633. extern int    *nshpclose();        /* close pipe */
  1634. SHAR_EOF
  1635. if test 113 -ne "`wc -c nshpopen.h`"
  1636. then
  1637. echo shar: error transmitting nshpopen.h '(should have been 113 characters)'
  1638. fi
  1639. cat << \SHAR_EOF > srtunq.c
  1640. /* Sorting function that inserts strings one at a time into memory.
  1641.  * Strings are null terminated.
  1642.  * Only uniq strings are stored (no count is kept of how many)
  1643.  * Any memory used is freed on init (or re-init).
  1644.  *
  1645.  * Author: Stephen Uitti, PUCC, 1985
  1646.  * libsrtunq is copyright (C) Purdue University, 1985
  1647.  *
  1648.  * Permission is hereby given for its free reproduction and
  1649.  * modification for non-commercial purposes, provided that this
  1650.  * notice and all embedded copyright notices be retained.
  1651.  * Commercial organisations may give away copies as part of their
  1652.  * systems provided that they do so without charge, and that they
  1653.  * acknowledge the source of the software.
  1654.  */
  1655.  
  1656. #ifndef lint
  1657. static char *rcsid =
  1658.     "$Id: srtunq.c,v 1.4 86/08/30 21:35:36 ksb Exp Locker: ksb $";
  1659. #endif
  1660.  
  1661. #ifdef BSD2_9
  1662. #include <sys/types.h>
  1663. #endif
  1664. #ifdef notdef            /* a comment that allows comments. */
  1665.  * use:
  1666.  * #include <local/srtunq.h>            /* defines, etc */
  1667.  * struct srtent d;                /* data structure foothold */
  1668.  * char *p;                    /* temp */
  1669.  * srtinit(&d);                    /* init the structure */
  1670.  * if ((p = srtin(&d, "foo", NULL)) != NULL) err(p);    /* add the data */
  1671.  *    ...
  1672.  * srtgti(&d);                    /* init for get */
  1673.  * p = srtgets(&d);                /* get next entry */
  1674.  *    ...
  1675.  * srtfree(&d);                    /* delete the structure */
  1676. #endif
  1677.  
  1678. #include <stdio.h>            /* for null */
  1679. #include <sys/types.h>            /* for void, in V7 */
  1680. #include "srtunq.h"            /* for srtunq structs & functions */
  1681. /* #include <local/srtunq.h>        /* for srtunq structs & functions */
  1682.  
  1683. /* libc functions */
  1684. char   *malloc();            /* need more memory */
  1685. char   *strcpy();            /* copy string */
  1686.  
  1687. /* srtgti - init get string function */
  1688. void
  1689. srtgti(ent)
  1690. struct srtent *ent;
  1691. {
  1692.     ent->srt_next = ent->srt_top;
  1693.     if (ent->srt_next == NULL)
  1694.     return;
  1695.     while (ent->srt_next->srt_less != NULL)
  1696.     ent->srt_next = ent->srt_next->srt_less;
  1697. }
  1698.  
  1699. /* srtgets - get next string from sorted list, NULL if none more. */
  1700. /* The least shall be first... and the greatest shall be last */
  1701. char *
  1702. srtgets(ent)
  1703. struct srtent *ent;
  1704. {
  1705.     register struct srtbl *s;        /* tmp */
  1706.     register char *p;            /* ret val */
  1707.  
  1708.     if ((s = ent->srt_next) == NULL)
  1709.     return NULL;
  1710.     p = s->srt_str;            /* ret val */
  1711.     if (s->srt_more != NULL) {
  1712.     s = s->srt_more;        /* go one more */
  1713.     while (s->srt_less != NULL)    /* then all the way less */
  1714.         s = s->srt_less;
  1715.     ent->srt_next = s;
  1716.     return p;
  1717.     }
  1718.     while (s != ent->srt_top && s->srt_prev->srt_more == s)
  1719.     s = s->srt_prev;        /* back down any more's */
  1720.     if (s == ent->srt_top)
  1721.     s = NULL;            /* no more */
  1722.     else
  1723.     s = s->srt_prev;
  1724.     ent->srt_next = s;
  1725.     return p;
  1726. }
  1727.  
  1728. /* srtinit - init the database tag */
  1729. void
  1730. srtinit(ent)
  1731. struct srtent *ent;
  1732. {
  1733.     ent->srt_top = NULL;        /* erase any knowledge of it */
  1734.     ent->srt_next = NULL;        /* extractions at the begining */
  1735. }
  1736.  
  1737. /* srtfree - delete all the data, init the tag */
  1738. void
  1739. srtfree(ent)
  1740. struct srtent *ent;
  1741. {
  1742.     if (ent->srt_top == NULL)        /* is the structure empty? */
  1743.     return;                /* yes - exit */
  1744.     srtdtree(ent->srt_top);
  1745.     free((char *)ent->srt_top);        /* clean up last struct */
  1746.     srtinit(ent);            /* init the tag */
  1747. }
  1748.  
  1749. /* srtdtree - recursive tree delete
  1750.  * frees all less & more entries pointed to by the srt struct */
  1751. void
  1752. srtdtree(srt)
  1753. register struct srtbl *srt;
  1754. {
  1755.     if (srt->srt_less != NULL) {
  1756.     srtdtree(srt->srt_less);
  1757.     free((char *)srt->srt_less);
  1758.     srt->srt_less = NULL;        /* for consistency */
  1759.     }
  1760.     if (srt->srt_more != NULL) {
  1761.     srtdtree(srt->srt_more);
  1762.     free((char *)srt->srt_more);
  1763.     srt->srt_more = NULL;
  1764.     }
  1765. }
  1766.  
  1767. /* srtin - insert string sorted & unique.
  1768.  * returns NULL if good, else error message string. */
  1769. char *
  1770. srtin(ent, str, compar)
  1771. struct srtent *ent;
  1772. char *str;
  1773. int (*compar)();            /* if NULL: use strcmp */
  1774. {
  1775.     register char *p;            /* temp string pointer */
  1776.     register i;                /* string compare result */
  1777.     register struct srtbl *s;        /* temp */
  1778.     register struct srtbl *srtold;    /* old temp */
  1779.  
  1780.     s = srtold = ent->srt_top;
  1781.     while (s != NULL) {
  1782.         if ((i = (compar == NULL ?
  1783.         strcmp(str, s->srt_str) : (*compar)(str, s->srt_str))) == 0)
  1784.         return NULL;        /* found: do nothing - "good" */
  1785.     srtold = s;
  1786.     if (i > 0)
  1787.         s = s->srt_more;
  1788.     else
  1789.         s = s->srt_less;
  1790.     }
  1791.     if ((p = malloc((unsigned)(strlen(str) + sizeof(struct srtbl)))) == NULL)
  1792.     return "srtin: warning - out of memory"; /* soft error - caller \n */
  1793.     s = (struct srtbl *)p;
  1794.     if (srtold == NULL) {        /* empty list */
  1795.     ent->srt_top = s;
  1796.     srtold = ent->srt_top;
  1797.     } else {
  1798.     if (i > 0)
  1799.         srtold->srt_more = s;
  1800.     else
  1801.         srtold->srt_less = s;
  1802.     }
  1803.     s->srt_prev = srtold;
  1804.     s->srt_less = NULL;
  1805.     s->srt_more = NULL;
  1806.     (void) strcpy(s->srt_str, str);
  1807.     return NULL;
  1808. }
  1809. SHAR_EOF
  1810. if test 4678 -ne "`wc -c srtunq.c`"
  1811. then
  1812. echo shar: error transmitting srtunq.c '(should have been 4678 characters)'
  1813. fi
  1814. cat << \SHAR_EOF > srtunq.h
  1815. /* include file for memory resident unique sorting routines.
  1816.  *
  1817.  * Written & hacked by Stephen Uitti, PUCC staff, ach@pucc-j, 1985
  1818.  * libsrtunq is copyright (C) Purdue University, 1985
  1819.  *
  1820.  * Permission is hereby given for its free reproduction and
  1821.  * modification for non-commercial purposes, provided that this
  1822.  * notice and all embedded copyright notices be retained.
  1823.  * Commercial organisations may give away copies as part of their
  1824.  * systems provided that they do so without charge, and that they
  1825.  * acknowledge the source of the software.
  1826.  */
  1827.  
  1828. /* database entry */
  1829. struct srtbl {
  1830.     struct srtbl *srt_prev;        /* parent */
  1831.     struct srtbl *srt_less;        /* something < srt_str */
  1832.     struct srtbl *srt_more;        /* something > srt_str */
  1833.     char srt_str[1];            /* dynamic: 1 for null at EOS */
  1834. };
  1835.  
  1836. /* database tag */
  1837. typedef struct srtent {
  1838.     struct srtbl *srt_top;        /* root of the tree */
  1839.     struct srtbl *srt_next;        /* pointer for srtget */
  1840. } SRTUNQ;
  1841.  
  1842. /* The functions */
  1843. void    srtinit();            /* init for srtin */
  1844. void    srtdtree();            /* recursive delete of subtree */
  1845. char   *srtin();            /* insert string - return err */
  1846. void    srtgti();            /* init for srtgets */
  1847. char   *srtgets();            /* get next string */
  1848. void    srtfree();            /* free a database */
  1849. SHAR_EOF
  1850. if test 1244 -ne "`wc -c srtunq.h`"
  1851. then
  1852. echo shar: error transmitting srtunq.h '(should have been 1244 characters)'
  1853. fi
  1854. cat << \SHAR_EOF > maketd.sh
  1855. #! /bin/sh
  1856. #
  1857. # maketd - generates file dependencies for makefiles using cc -M
  1858. #
  1859. PATH=/usr/local/bin:/bin:/usr/bin:/usr/ucb
  1860. export PATH
  1861.  
  1862. progname=`basename $0`
  1863.  
  1864. # Name of the Makefile which will be edited to add the dependencies
  1865. if [ $# = 0 ] ; then
  1866.     cat << EOF
  1867. usage: $progname [-a] [-d] [-m<file>] [-o<directory>] [-D...] [-I...] [-U...]
  1868.           [<file> ...] [-T <file> ...]
  1869. EOF
  1870.     exit
  1871. fi
  1872.  
  1873. DEPFILE=/tmp/mtd3$$.tmp
  1874. touch $DEPFILE
  1875. EDDFILE=/tmp/mtd4$$.tmp
  1876.  
  1877. trap 'rm -f $DEPFILE $EDDFILE ; exit ' 1 2 3 15
  1878.  
  1879. # Default values for -a, -d, -m and -o options
  1880. AOPTION="-e /\/usr\/include/d"
  1881. DOPTION=0
  1882. MAKEFILE=Makefile
  1883. OBJDIR=
  1884.  
  1885. # Collect in OPTIONS all options you want to pass on to the C preprocessor.
  1886. #       in SOURCES all files you want to create dependencies for
  1887. while [ -n "$1" ] ; do
  1888.     case $1 in
  1889.  
  1890.     -a)
  1891.         AOPTION=
  1892.     ;;
  1893.  
  1894.     -d)
  1895.         DOPTION=1
  1896.     ;;
  1897.  
  1898.     -m*)
  1899.         MAKEFILE=`expr $1 : '-m\(.*\)'`
  1900.     ;;
  1901.  
  1902.     -nonlocalo)
  1903.         echo "$progname: -nonlocalo option obsolete"
  1904.         exit 1
  1905.     ;;
  1906.  
  1907.     -o*)
  1908.         if [ "$1" = "-o" ] ; then
  1909.         echo    "$progname: -o option requires directory name"
  1910.         exit 1
  1911.         fi
  1912.         OBJDIR=`expr $1 : '-o\(.*\)'`
  1913.         if [ ! -d $OBJDIR ] ; then
  1914.         echo    "$progname: -o option: \"$OBJDIR\" is not a directory"
  1915.         exit 1
  1916.         fi
  1917.         OBJDIR="$OBJDIR/"
  1918.     ;;
  1919.  
  1920.     -[D,I,U]*)
  1921.         OPTIONS="$OPTIONS $1"
  1922.     ;;
  1923.  
  1924.     -T)
  1925.         shift
  1926.         TSOURCES="$*"
  1927.         set ""
  1928.     ;;
  1929.  
  1930.     -*)
  1931.         echo        "$progname: option \"$1\" unknown; ignored"
  1932.     ;;
  1933.  
  1934.     *)
  1935.         SOURCES="$SOURCES $1"
  1936.     ;;
  1937.     esac
  1938.     shift
  1939. done
  1940.  
  1941. #       Run everything through the preprocessor (using cc), sort this
  1942. #    output and remove duplictate lines.  If there is no '-a' option
  1943. #    remove all dependencies of the form '/usr/include/<file>'. Cc
  1944. #    will exit quietly if there are no source files.
  1945. /bin/cc -M $OPTIONS $SOURCES | sort | uniq | \
  1946.     sed $AOPTION \
  1947.     -e "s, \./, ,g" \
  1948.     -e "s,\.\./[a-zA-Z0-9]*/\.\.,\.\.,g" \
  1949.     -e "s,^,$OBJDIR," >> $DEPFILE
  1950.  
  1951. /bin/cc -M $OPTIONS $TSOURCES | sort | uniq | \
  1952.     sed $AOPTION \
  1953.     -e "s,\.o:,:," \
  1954.     -e "s, \./, ,g" \
  1955.     -e "s,\.\./[a-zA-Z0-9]*/\.\.,\.\.,g" \
  1956.     -e "s,^,$OBJDIR," >> $DEPFILE
  1957.  
  1958. # If DOPTION then cat file and exit, otherwise edit Makefile
  1959. if [ $DOPTION -eq 1 ] ; then
  1960.     cat $DEPFILE
  1961.     rm -f $DEPFILE $EDDFILE
  1962.     exit
  1963. fi
  1964.  
  1965. # Now start editing the Makefile
  1966. if [ ! -w $MAKEFILE ] ; then
  1967.     echo        "$progname: can't edit $MAKEFILE"
  1968.     rm -f $DEPFILE $EDDFILE
  1969.     exit 1
  1970. fi
  1971.  
  1972.  
  1973. # Make sure we have the "DO NOT DELETE" line in the Makefile
  1974. cat << EOF >> $MAKEFILE
  1975.  
  1976. # DO NOT DELETE THIS LINE - maketd DEPENDS ON IT
  1977. EOF
  1978.  
  1979. # Build the editor script to edit the Makefile later.
  1980. cat << EOF > $EDDFILE
  1981. /# DO NOT DELETE THIS LINE/,\$d
  1982. \$a
  1983. # DO NOT DELETE THIS LINE - maketd DEPENDS ON IT
  1984. # Dependencies generated at: `date`
  1985.  
  1986. EOF
  1987. cat $DEPFILE >> $EDDFILE
  1988. cat << EOF >> $EDDFILE
  1989.  
  1990. # DO NOT ADD ANYTHING HERE - WILL GO AWAY
  1991.  
  1992.